home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1997 August / Walnut Creek CDROM.7z / LISTINGS / V_12_09 / SINGLE2 / COUT.ZIP / CSTRWND.CPP next >
Encoding:
C/C++ Source or Header  |  1993-10-26  |  7.8 KB  |  274 lines

  1. //  CStrWnd.cpp
  2.  
  3. //  See CStrWnd.h for a definition of what the
  4. //  class CStrWnd does
  5.                         
  6. #include     "stdafx.h"
  7. #include    "cstrwnd.h"
  8. #include    "strdetab.h"
  9.  
  10. CStrWnd::CStrWnd (const char * window_name)
  11. {
  12. //    VERIFY (LoadAccelTable ("CStrWndAccelTable"));
  13. //    Assume accelerators loaded by parent application
  14. VERIFY (Create (NULL, window_name,
  15.                 WS_CHILD | WS_VISIBLE | WS_OVERLAPPEDWINDOW | WS_VSCROLL, rectDefault,
  16.                 NULL));
  17. SetFocus ();
  18. current_first_row = 0; current_first_col = 0;
  19. h_scroll_flag = 0;
  20. length_of_longest_line = 0;
  21. }
  22.  
  23. BEGIN_MESSAGE_MAP (CStrWnd, CMDIChildWnd)
  24.     //{{AFX_MSG_MAP(CStrWnd)
  25.     ON_WM_PAINT ()
  26.     ON_WM_VSCROLL ()
  27.     ON_WM_HSCROLL ()
  28.     ON_WM_KEYDOWN()
  29.     //}}AFX_MSG_MAP
  30. END_MESSAGE_MAP ()
  31.  
  32. afx_msg void CStrWnd::OnPaint ()
  33. {
  34. CPaintDC dc (this);
  35. //  Use a fixed-pitch font for better presentation
  36. VERIFY (dc.SelectStockObject(OEM_FIXED_FONT) != NULL);
  37.  
  38. //  First find out number of lines in the window
  39. TEXTMETRIC tm;
  40. VERIFY (dc.GetTextMetrics (&tm));
  41. const int char_height = tm.tmHeight
  42.                         + tm.tmExternalLeading;
  43. const int char_width = tm.tmAveCharWidth;
  44. CRect rect;
  45. GetClientRect (rect);
  46. no_of_lines = rect.Height () / char_height;
  47. no_of_chars_in_line = rect.Width () / char_width;
  48.  
  49. //  Set up the tab stop positions
  50. const int tab_interval = 4;
  51. const int no_of_tabs = 120 / tab_interval;
  52. int char_tab_stops [no_of_tabs];
  53. for (int i = 0; i < no_of_tabs; i++)
  54.     char_tab_stops [i] = (i + 1) * tab_interval;
  55.  
  56. //  Write a window_full of text
  57.  
  58. for (int lc = 0;
  59.      lc < no_of_lines
  60.      && current_first_row + lc
  61.         < text_buffer.GetSize ();
  62.      lc++)
  63.     {
  64.     const int max_line_length = 256;
  65.     char out_buf [max_line_length + 1];
  66.     int line_length;
  67.     //  Convert tabs to spaces
  68.     strdetab (out_buf, max_line_length,
  69.               text_buffer [current_first_row + lc],
  70.               no_of_tabs, char_tab_stops,
  71.               &line_length);
  72.     //  Get pointer to first char in line for output
  73.     const char * first_char = out_buf
  74.                               + current_first_col;
  75.     //  Update record of longest line length
  76.     if (length_of_longest_line < line_length)
  77.         length_of_longest_line = line_length;
  78.     //  Call up horizontal scroll bar if needed
  79.     if (line_length > no_of_chars_in_line)
  80.         h_scroll_flag = 1;
  81.     dc.TextOut (0, lc * char_height, first_char,
  82.                 line_length - current_first_col);
  83.     }
  84. if (h_scroll_flag) ShowScrollBar (SB_HORZ, TRUE);
  85. }
  86.  
  87. afx_msg void CStrWnd::OnVScroll (UINT nSBCode,
  88.                                  UINT npos,
  89.                                  CScrollBar * /* pBar */)
  90. {
  91. int min_scroll_pos, max_scroll_pos,
  92.     max_index = text_buffer.GetSize () - 1,
  93.     scrolled = 1;
  94. if (max_index < 0) max_index = 0;
  95.     //  Cater for no lines in text_buffer
  96. switch (nSBCode)
  97.     {
  98.     case SB_LINEDOWN:
  99.         current_first_row++; break;
  100.     case SB_PAGEDOWN:
  101.         current_first_row += no_of_lines - 1; break;
  102.     case SB_LINEUP:
  103.         current_first_row--; break;
  104.     case SB_PAGEUP:
  105.         current_first_row -= no_of_lines - 1; break;
  106.     case SB_THUMBPOSITION:
  107.         GetScrollRange (SB_VERT, &min_scroll_pos,
  108.                         &max_scroll_pos);
  109.         current_first_row =
  110.             (max_index * (npos - min_scroll_pos))
  111.              / (max_scroll_pos - min_scroll_pos);
  112.         break;
  113.     default:
  114.     //  We did nothing, so do not update the window!
  115.         scrolled = 0; break;
  116.     }
  117.  
  118. if (scrolled)
  119.     {
  120.     //  Now make sure that the current row is in range
  121.     if (current_first_row < 0) current_first_row = 0;
  122.     if (current_first_row > max_index)
  123.         current_first_row = max_index;
  124.     Invalidate (TRUE);
  125.     SetVerticalScroll ();
  126.     UpdateWindow ();
  127.     }
  128. }
  129.  
  130. afx_msg void CStrWnd::OnHScroll (UINT nSBCode,
  131.                                  UINT npos,
  132.                                  CScrollBar * /* pBar */)
  133. {
  134. int min_scroll_pos, max_scroll_pos,
  135.     scrolled = 1;
  136. GetScrollRange (SB_VERT, &min_scroll_pos,
  137.                 &max_scroll_pos);
  138. switch (nSBCode)
  139.     {
  140.     case SB_LINERIGHT:
  141.         current_first_col++; break;
  142.     case SB_PAGERIGHT:
  143.         current_first_col += 10; break;
  144.     case SB_LINELEFT:
  145.         current_first_col--; break;
  146.     case SB_PAGELEFT:
  147.         current_first_col -= 10; break;
  148.     case SB_LEFT:
  149.         current_first_col = 0; break;
  150.     case SB_RIGHT:
  151.         current_first_col = length_of_longest_line - 1;
  152.         break;
  153.     case SB_THUMBPOSITION:
  154.         current_first_col =
  155.             ((length_of_longest_line - 1)
  156.              * (npos - min_scroll_pos))
  157.              / (max_scroll_pos - min_scroll_pos);
  158.         break;
  159.     default:
  160.         //  We did nothing, so do not update  window!
  161.         scrolled = 0; break;
  162.     }
  163.  
  164. if (scrolled)
  165.     {
  166.     //  Now ensure that we are within limits
  167.     if (current_first_col < 0) current_first_col = 0;
  168.     if (current_first_col >= length_of_longest_line)
  169.         current_first_col = length_of_longest_line - 1;
  170.     Invalidate (TRUE);
  171.     if (h_scroll_flag)
  172.         SetScrollPos (SB_HORZ,
  173.                   ((max_scroll_pos - min_scroll_pos)
  174.                   * current_first_col)
  175.                   / (length_of_longest_line -1)
  176.                   + min_scroll_pos,
  177.                   TRUE);
  178.     UpdateWindow ();
  179.     }
  180. }
  181.  
  182. afx_msg void CStrWnd::OnKeyDown (UINT nChar,
  183.                                  UINT nRepCnt,
  184.                                  UINT nFlags)
  185. {
  186. BOOL control_key_down = GetKeyState(VK_CONTROL) < 0;
  187.  
  188. switch (nChar)
  189.     {
  190.     case VK_DOWN:
  191.         OnVScroll (SB_LINEDOWN, 0, NULL); 
  192.         break;
  193.     case VK_NEXT:                   // Page down
  194.         OnVScroll (SB_PAGEDOWN, 0, NULL); 
  195.         break;
  196.     case VK_UP:
  197.         OnVScroll (SB_LINEUP, 0, NULL); 
  198.         break;
  199.     case VK_PRIOR:                  // Page up
  200.         OnVScroll (SB_PAGEUP, 0, NULL); break;
  201.     case VK_LEFT:
  202.         OnHScroll (control_key_down ? SB_PAGELEFT : SB_LINELEFT, 
  203.                    0, NULL); 
  204.         break;
  205.     case VK_HOME:
  206.         if (control_key_down)
  207.             OnDocStart ();
  208.         else
  209.             OnHScroll (SB_LEFT, 0, NULL); 
  210.         break;
  211.     case VK_RIGHT:                                  
  212.         OnHScroll (control_key_down ? SB_PAGERIGHT : SB_LINERIGHT, 
  213.                    0, NULL); 
  214.         break;
  215.     case VK_END:
  216.         if (control_key_down)
  217.             OnDocEnd ();
  218.         else
  219.             OnHScroll (SB_RIGHT, 0, NULL); 
  220.         break;
  221.     default:
  222.         CMDIChildWnd::OnKeyDown(nChar, nRepCnt, nFlags);
  223.  
  224.     }
  225. }
  226.  
  227. afx_msg void CStrWnd::OnDocStart ()
  228. {
  229. int min_scroll_pos, max_scroll_pos;
  230. GetScrollRange (SB_VERT, &min_scroll_pos,
  231.                 &max_scroll_pos);
  232. Invalidate (TRUE);
  233. current_first_row = 0;
  234. SetScrollPos (SB_VERT, min_scroll_pos, TRUE);
  235. UpdateWindow ();
  236. }
  237.  
  238. afx_msg void CStrWnd::OnDocEnd ()
  239. {
  240. int min_scroll_pos, max_scroll_pos;
  241. GetScrollRange (SB_VERT, &min_scroll_pos,
  242.                 &max_scroll_pos);
  243. Invalidate (TRUE);
  244. current_first_row = text_buffer.GetUpperBound () - 4;
  245. //  Leave 4 lines on the screen
  246. if (current_first_row < 0) current_first_row = 0;
  247. SetScrollPos (SB_VERT, max_scroll_pos, TRUE);
  248. UpdateWindow ();
  249. }
  250.  
  251. void CStrWnd::UpdateScreen ()
  252. {
  253. current_first_row = text_buffer.GetUpperBound ()
  254.                     - no_of_lines;
  255. if (current_first_row < 0) current_first_row = 0;
  256. SetVerticalScroll ();
  257. Invalidate (TRUE);
  258. UpdateWindow ();
  259. }
  260.  
  261. void CStrWnd::SetVerticalScroll ()
  262. {
  263. int min_scroll_pos, max_scroll_pos,
  264.     max_index = text_buffer.GetUpperBound ();
  265. GetScrollRange (SB_VERT, &min_scroll_pos,
  266.                 &max_scroll_pos);
  267. SetScrollPos (SB_VERT,
  268.               ((max_scroll_pos - min_scroll_pos )
  269.                 * current_first_row)
  270.               / ((max_index > 0) ? max_index : 1)
  271.               + min_scroll_pos,
  272.               TRUE);
  273. }
  274.